package com.lsc.record.core.service.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.lsc.record.common.BooleanResult;
import com.lsc.record.core.entity.DmType;
import com.lsc.record.core.entity.DmTypeAttr;
import com.lsc.record.core.entity.TableEntity;
import com.lsc.record.core.entity.TableField;
import com.lsc.record.core.mapper.DmTypeAttrMapper;
import com.lsc.record.core.mapper.DmTypeMapper;
import com.lsc.record.core.service.TableQueryServcie;
import com.lsc.record.core.service.TypeService;
import com.lsc.record.core.util.RowConvertUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.spring.service.impl.ServiceImpl;


@Service
public class TypeServiceImpl extends ServiceImpl<DmTypeMapper, DmType> implements TypeService {

	@Resource
	private TableQueryServcie tableQuery;
	
	@Resource
	private DmTypeAttrMapper attrMapper;
	
	@Override
	public BooleanResult appendAttr(DmTypeAttr attr, String typeId) throws Exception {
		BooleanResult result = BooleanResult.error();
		attr.setTypeId(typeId);
		
		DmType type = this.mapper.selectOneWithRelationsById(typeId);
		String tableName = type.getTableName();
		Set<String> fieldKeys = tableQuery.fieldsKeys(tableName, true);
		
		try {
			
			
			
			int data = attrMapper.insert(attr, true);
			if(data>0) {
				if(!fieldKeys.contains(attr.getName().toLowerCase())) {
					tableQuery.addField(tableName,attr);
				}
				result = BooleanResult.success("");
			}
		}catch (Exception e) {
			result = BooleanResult.error(e.getLocalizedMessage());
			throw new Exception("添加字段出现异常");
		}
		return result;
	}

	@Override
	public BooleanResult removeAttr(String attrId) {
		BooleanResult result = BooleanResult.error();
		int del = attrMapper.deleteById(attrId);
		if(del>0) {
			result = BooleanResult.success();
		}
		return result;
	}

	@Override
	public BooleanResult updateAttr(DmTypeAttr attr) {
		BooleanResult result = BooleanResult.error();		
		int up = attrMapper.update(attr, true);
		if(up>0) {
			result = BooleanResult.success();
		}
		return result;
	}

	@Override
	public BooleanResult initAttr(String typeId) {
		BooleanResult result = BooleanResult.error();
		return result;
	}

	@Override
	public boolean existAttr(String name, String typeId) {
		List<Row> list = Db.selectListBySql("select count(*) as count_size from dm_type_attr where type_id=? and (name=? or name=?)", typeId,name.toLowerCase(),name.toUpperCase());
		list = RowConvertUtil.toRowListLowerKey(list);
		Long count = list.get(0).getLong("count_size");
		return count>0;
	}

	@Override
	public DmType getWithRelationById(String id) {
		return this.mapper.selectOneWithRelationsById(id);
	}

	@Override
	public String getTypeQueryColumn(String typeId) {
		StringBuffer sb = new StringBuffer("");
		Set<String> exFields = new HashSet<>();
		exFields.add("version");
		exFields.add("is_deleted");
		exFields.add("delete_user");
		exFields.add("delete_time");
		DmType type = this.getWithRelationById(typeId);
		List<DmTypeAttr> attrList = type.getItems();
		for (DmTypeAttr attr : attrList) {
			String fieldname = attr.getName().toLowerCase();
			if(!exFields.contains(fieldname)) {
				if(sb.length()>0) {
					sb.append(",");
				}
				sb.append(fieldname);
			}
		}
		return sb.toString();
	}

	@Override
	public void initType(List<TableEntity> tableList) {
		for (TableEntity te : tableList) {
			if(te.getFields()==null || te.getFields().size()<1) {
				continue;
			}
			if(StringUtils.isEmpty(te.getTableType()) || !te.getTableType().toLowerCase().equals("table")) {
				continue;
			}
			if(!te.getTableName().toLowerCase().startsWith("dm_")) {
				continue;
			}
			DmType type = new DmType();
			type.setName(te.getTableName());
			type.setTableName(te.getTableName());
			
			if(te.getTableName().toLowerCase().equals("dm_document")) {
				type.setSnCode("100");
			}
			if(te.getTableName().toLowerCase().equals("dm_record")) {
				type.setSnCode("200");
			}
			this.save(type);
			createAttr(te.getFields(),type);
		}
	
	}
	/**
	 * 从数据库获取的字段信息给类型，初始化使用
	 * @param fields
	 * @param type
	 */
	private void createAttr(List<TableField> fields,DmType type) {
		String typeId = type.getId();
		List<DmTypeAttr> attrList= new ArrayList<>();
		for (TableField tf : fields) {
			DmTypeAttr attr = new DmTypeAttr();
			attr.setName(tf.getColumnName());
			attr.setTitle(tf.getComments());
			attr.setDataType(tf.getDataType());
			attr.setDataLength(tf.getDataLength());
			attr.setDataDefault(tf.getDataDefault());
			attr.setDataNullable(tf.getNullable());
			attr.setTypeId(typeId);
			attrList.add(attr);
		}
		
		for (DmTypeAttr attr : attrList) {
			attrMapper.insert(attr, true);
		}
		
	}

	@Override
	public List<DmType> list(boolean hasRelation) {
		if(hasRelation) {
			return this.mapper.selectAllWithRelations();
		}else {
			return this.list();
		}
		
	}

	@Override
	public DmType getByTypeName(String typeName) {
		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.in("name", typeName.toLowerCase(),typeName.toUpperCase());
		Optional<DmType> typeOpt = this.getOneOpt(queryWrapper);
		if(typeOpt.isPresent()) {
			return this.getWithRelationById(typeOpt.get().getId());
		}else {
			return null;
		}
	}

	@Override
	public DmType createSubType(String superTypeId, String typeName,String snCode) {
		DmType superType = this.getWithRelationById(superTypeId);
		List<DmTypeAttr> attrList = superType.getItems();
		DmType newType = superType;
		newType.setId(null);
		newType.setSuperId(superTypeId);
		newType.setSnCode(snCode);
		newType.setName(typeName);
		newType.setCreateTime(null);
		newType.setCreateUser(null);
		newType.setUpdateTime(null);
		newType.setUpdateUser(null);
		this.save(newType);
		
		for (DmTypeAttr dmTypeAttr : attrList) {
			if(dmTypeAttr.getName().equals("YPE_NAME")) {
				dmTypeAttr.setDataDefault(typeName);
			}
			dmTypeAttr.setId(null);
			dmTypeAttr.setTypeId(newType.getId());
			dmTypeAttr.setIsInherited(true);
			attrMapper.insert(dmTypeAttr, true);
		}
		newType= this.getWithRelationById(newType.getId());
		return newType;
	}

}
